SI649 W23 Altair Homework #4¶

Overview¶

We'll focus on maps and cartrographic visualization. In this lab, you will practice:

  • Point Maps
  • Symbol Maps
  • Choropleth maps
  • Interactions with maps

Lab Instructions¶

  • Save, rename, and submit the ipynb file (use your username in the name).
  • Complete all the checkpoints, to create the required visualization at each cell.
  • Run every cell (do Runtime -> Restart and run all to make sure you have a clean working version), print to pdf, submit the pdf file.
  • If you end up stuck, show us your work by including links (URLs) that you have searched for. You'll get partial credit for showing your work in progress.
In [41]:
import pandas as pd
import altair as alt
from vega_datasets import data

alt.data_transformers.disable_max_rows()

df = pd.read_csv('https://raw.githubusercontent.com/dallascard/si649_public/main/altair_hw4/airports.csv')
url = "https://raw.githubusercontent.com/dallascard/si649_public/main/altair_hw4/small-airports.json"

Visualization 1: Dot Density Map¶

vis1 Description of the visualization:

We want to visualize the density of small airports in the world. Each small airport is represented by a dot. The visualization has two layers:

  • The base layer shows the outline of the world map.
  • The point map shows different small airports.
  • The tooltip shows the name of the airport.

Hint:

  • How can we show continents on the map? Which object can be used from the json dataset ?
  • How can we show only small airports on the map?
In [42]:
df = df[df['type']=='small_airport']
world_map = alt.topo_feature(url, feature='continent')
base = alt.Chart(world_map).mark_geoshape(
    fill='lightgray'
).project('mercator')
points = alt.Chart(df).mark_circle(size=14, color='red').encode(
    longitude='longitude_deg:Q',
    latitude='latitude_deg:Q',
    tooltip='name:N'
)
map_vis = base + points
map_vis.properties(width=900, height=800)
Out[42]:

Visualization 2: Propotional Symbol¶

vis2 Description of the visualization:

The visualization shows faceted maps pointing the 20 most populous cities in the world by 2100. There are two layers in faceted charts:

  • The base layer shows the map of countries.
  • The second layer shows size encoded points indicating the population of those countries.
  • Tooltip shows city name and population.

Hint:

  • Which projection has been used in individual charts?
  • How to create a faceted chart with different years and 2 columns?
In [43]:
countries_url = data.world_110m.url
source = 'https://raw.githubusercontent.com/dallascard/SI649_public/main/altair_hw4/population_prediction.csv'
In [44]:
df2 = pd.read_csv(source)
In [45]:
world = alt.topo_feature(countries_url, feature='countries')
base = alt.Chart(world).mark_geoshape(
    fill='lightgray',
    stroke='white'
).project(type='equirectangular').properties(width=400, height=400)
points = alt.Chart().mark_circle(opacity=0.7, fill='green', stroke='white').encode(
    longitude='lon:Q',
    latitude='lat:Q',
    size=alt.Size('population:Q', title='Population(million)', scale=alt.Scale(range=[300, 1500])),
    tooltip=[alt.Tooltip('city:N'), alt.Tooltip('population:Q')]
)
map_faceted = alt.layer(
    base, points
).facet(
    'year:N',
    columns=2,
    data=df2
).properties(
    title='The 20 most Populous Cities in the world by 2100',
)
map_faceted
Out[45]:

Visualization 3: Hurricane Trajectories¶

vis3 Description of the visualization:

Create a map that shows the paths (trajectories) of the 2017 hurricanes. Filter the data so that only 2017 hurricanes are shown. Remove Alaska and Hawaii from the map (Filter out ids 2 and 15).

Hint:

  • How will you filter out 2017 hurricanes?
  • Which object can be used to show state boundaries?
In [46]:
states_url = data.us_10m.url
hurricane_data = pd.read_csv('https://raw.githubusercontent.com/dallascard/SI649_public/main/altair_hw4/hurdat2.csv')
hurricane_data = hurricane_data[hurricane_data['identifier'].str[-4:] == '2017']
hurricane_data
Out[46]:
identifier name num_pts record_id status latitude longitude max_wind min_pressure datetime
49693 AL012017 ARLENE 27 NaN EX 35.8 -50.3 55 992 2017-04-16T06:00:00
49694 AL012017 ARLENE 27 NaN EX 35.1 -49.5 55 989 2017-04-16T12:00:00
49695 AL012017 ARLENE 27 NaN EX 34.4 -48.7 55 986 2017-04-16T18:00:00
49696 AL012017 ARLENE 27 NaN EX 33.7 -47.8 50 987 2017-04-17T00:00:00
49697 AL012017 ARLENE 27 NaN EX 33.2 -47.0 45 988 2017-04-17T06:00:00
... ... ... ... ... ... ... ... ... ... ...
50298 AL192017 RINA 21 NaN TS 38.3 -48.8 45 994 2017-11-08T12:00:00
50299 AL192017 RINA 21 NaN TS 40.1 -49.0 45 992 2017-11-08T18:00:00
50300 AL192017 RINA 21 NaN TS 41.8 -48.8 45 991 2017-11-09T00:00:00
50301 AL192017 RINA 21 NaN LO 43.6 -48.0 40 993 2017-11-09T06:00:00
50302 AL192017 RINA 21 NaN LO 45.5 -47.0 40 995 2017-11-09T12:00:00

610 rows × 10 columns

In [47]:
states = alt.topo_feature(data.us_10m.url, feature='states')
base = alt.Chart(states).mark_geoshape(
    fill=None,
    stroke='black'
).transform_filter(
    "datum.id !== 2 && datum.id !== 15"
).project('mercator').properties(width=800, height=500)

hurricane_paths = alt.Chart(hurricane_data).mark_line(color = 'blue').encode(
    longitude='longitude:Q',
    latitude='latitude:Q',
)
base + hurricane_paths
Out[47]:

Visualization 4: Choropleth Map¶

vis4

Interaction

vis4

Description of the visualization:

The visualization has a choropleth map showing the population of different states and a sorted bar chart showing the top 15 states by population. These charts are connected using a click interaction.

Hint

  • Which object can be used to show states on the map?
  • Which transform can be used to add population data to the geographic data? How can we combine two datasets in Altair?
In [ ]:
 
In [48]:
state_map = data.us_10m.url
state_pop = data.population_engineers_hurricanes()[['state', 'id', 'population']]
state_map = alt.topo_feature(state_map, 'states')
selection = alt.selection_point(fields=['id']) 

map_chart = alt.Chart(state_map).mark_geoshape().encode(
    color='population:Q',
    tooltip=['state:N', 'population:Q'],
    opacity=alt.condition(selection, alt.value(1), alt.value(0.3))
).transform_lookup(
    lookup='id',
    from_=alt.LookupData(state_pop, 'id', ['state', 'population'])
).project(
    type='albersUsa'
).add_params(
    selection
).properties(
    width=400,
    height=300
)

bar_chart = alt.Chart(state_pop).mark_bar().encode(
    y=alt.Y('state:N', sort='x', title='State'),
    x=alt.X('population:Q', title='Population'),
    color='population:Q',
    tooltip=['state:N', 'population:Q'],
    opacity=alt.condition(selection, alt.value(1), alt.value(0.3))
).add_params(
    selection
).transform_window(
    rank='rank(population)',
    sort=[alt.SortField('population', order='descending')]
).transform_filter(
    'datum.rank <= 15'
).properties(
    width=400,
    height=300,
    title='Top 15 States by Population'
)

final_chart = map_chart | bar_chart
final_chart
Out[48]: